﻿using System;
using System.Linq;
using System.Text;
using hlavny.modul1;
using hlavny.modul2;
using System.Collections.Generic;

namespace hlavny.modul4
{
    /// <summary>
    /// zaznam predstavuje jeden riadok v databaze.
    /// Obsahuje list typov (akeho typu su stlpce v tom zazname) a este obsahuje list hodnot
    /// </summary>
    class Zaznam
    {
        #region privatne atributy
        private CSysTables sysTables;
        private CSysColumns sysColumns;

        private Dictionary<int, modul1.Object> hodnotyDictionary = new Dictionary<int, modul1.Object>();

        private int pocetStlpcov = 0;
        private int velkostZaznamu = 0; // velkost v bitoch

        private int rowId = int.MinValue;
        #endregion





        #region properties
        public int VelkostZaznamu
        {
            get { return velkostZaznamu; }
            set { velkostZaznamu = value; }
        }

        public int RowId
        {
            get { return rowId; }
            set { rowId = value; }
        }
        #endregion





        #region metody
        private void Init(CSysTables paSysTables, CSysColumns paSysColumns, int paTabulkaId)
        {
            this.sysTables = paSysTables;
            this.sysColumns = paSysColumns;

            foreach (int iCisloStlpca in sysTables.Tables[sysTables.GetTableIndex(paTabulkaId)].ColumnsIds)
            {
                CAttribute stlpec = sysColumns.Columns[sysColumns.GetAttributeIndex(iCisloStlpca)];
                modul1.Object vkladanyObjekt;
                switch (stlpec.Type)
                {
                    case CTypes.EnumTypes.Boolean:
                        vkladanyObjekt = new modul1.Boolean(true);
                        break;
                    case CTypes.EnumTypes.Byte:
                        vkladanyObjekt = new modul1.Byte(0);
                        break;
                    case CTypes.EnumTypes.DoublePrecision:
                        vkladanyObjekt = new modul1.DoublePrecision(0.0);
                        break;
                    case CTypes.EnumTypes.Character:
                        vkladanyObjekt = new modul1.Character(stlpec.Length);
                        break;
                    case CTypes.EnumTypes.Integer:
                        vkladanyObjekt = new modul1.Integer(0);
                        break;
                    case CTypes.EnumTypes.LongInt:
                        vkladanyObjekt = new modul1.LongInt(0);
                        break;
                    case CTypes.EnumTypes.Real:
                        vkladanyObjekt = new modul1.Real(0);
                        break;
                    case CTypes.EnumTypes.SmallInt:
                        vkladanyObjekt = new modul1.SmallInt(0);
                        break;
                    case CTypes.EnumTypes.Word:
                        vkladanyObjekt = new modul1.Word(0);
                        break;
                    default:
                        throw new Exception("Neznamy typ");
                }
                velkostZaznamu += vkladanyObjekt.ToByte().Length;
                hodnotyDictionary.Add(stlpec.Id, vkladanyObjekt);
                pocetStlpcov++;
            }
        }

        public Zaznam(CSysTables paSysTables, CSysColumns paSysColumns, int paTabulkaId)
        {
            this.Init(paSysTables, paSysColumns, paTabulkaId);
        }

        public Zaznam(CSysTables paSysTables, CSysColumns paSysColumns, int paTabulkaId, byte[] paBuffer)
        {
            this.Init(paSysTables, paSysColumns, paTabulkaId);
            this.FromByte(paBuffer);
        }

        public void FromByte(byte[] paBuffer)
        {
            if (paBuffer.Length != velkostZaznamu)
            {
                throw new Exception("Nespravny pocet bitov");
            }
            else
            {
                int[] kluce = hodnotyDictionary.Keys.ToArray();
                Array.Sort(kluce);
                byte[] pom;
                int posun = 0;
                foreach (int kluc in kluce)
                {
                    pom = new byte[hodnotyDictionary[kluc].ToByte().Length];
                    Array.Copy(paBuffer, posun, pom, 0, pom.Length);
                    hodnotyDictionary[kluc].FromByte(pom);
                    posun += pom.Length;
                }
            }
        }

        public byte[] ToByte()
        {
            /*
             * jeden zaznam na disku
             * +----------------------+-----------------+
             * | N x hodnota stlpca   | modul1.Object[] |
             * +----------------------------------------+
             */
            byte[] buffer = new byte[velkostZaznamu];

            int posunHodnot = 0;

            byte[] pom;
            int[] kluce = hodnotyDictionary.Keys.ToArray();
            Array.Sort(kluce);
            foreach (int kluc in kluce)
            {
                pom = hodnotyDictionary[kluc].ToByte();
                Array.Copy(hodnotyDictionary[kluc].ToByte(), 0, buffer, posunHodnot, pom.Length);
                posunHodnot += pom.Length;
            }
            return buffer;
        }


        public void AlterAtr(int pa_iStlpec, modul1.Object pa_oHodnota)
        {
            if (hodnotyDictionary.Keys.Contains(pa_iStlpec))
            {
                hodnotyDictionary[pa_iStlpec] = pa_oHodnota;
            }
            else
            {
                throw new Exception("Nenachadza sa");
            }
        }

        public modul1.Object GetValue(int paStlpecId)
        {
            return hodnotyDictionary[paStlpecId];
        }
        #endregion
    }
}
